﻿using System;
using System.Collections.Generic;
using System.Text;
using System.CodeDom;
using System.IO;

using EdgeStatz.ESSystems.Objects;

namespace EdgeStatz.ModelEngine.FormTools
{
    public class FormGenerator
    {
        TextWriter writer = null;

        List<CodeStatement> init_component = new List<CodeStatement> { };
        List<CodeStatement> setup_component = new List<CodeStatement> { };        
        List<string[]> component_list = new List<string[]> { };
        List<string[]> tabpage_list = new List<string[]> { };

        CodeCompileUnit cu = new CodeCompileUnit();
        CodeNamespace cn = new CodeNamespace("EdgeStatz.GeneratedForms");
        CodeTypeDeclaration ctd = null;

        string classname;
        //string idcol_name;
        FolderDefinition folderdef;
        TableDefinition tabledef;

        int tabindex = 0;
        bool istabbed = false;

        public FormGenerator(string classname, FolderDefinition folderdef, TableDefinition tabledef)
        {
            this.classname = classname;
            this.folderdef = folderdef;
            this.tabledef = tabledef;

            writer = new StreamWriter(GlobalSystemSettings.SystemFolderPath +
                (GlobalSystemSettings.SystemFolderPath.EndsWith("\\") ? "" : "\\") + classname + "_Form.cs", false);

            ctd = new CodeTypeDeclaration(classname);
            ctd.BaseTypes.Add(new CodeTypeReference(typeof(System.Windows.Forms.UserControl)));
            ctd.BaseTypes.Add(new CodeTypeReference(typeof(EdgeStatz.ESSystems.Objects.GeneratedForm)));

            AddImport("System");
            AddImport("System.Windows.Forms");
            AddImport("System.Drawing");

            AddImport("EdgeStatz.ESSystems.Objects");
            AddImport("EdgeStatz.ModelEngine.FolderTools");

            CodeConstructor constructor = new CodeConstructor();
            constructor.Attributes = MemberAttributes.Public;
            constructor.Statements.Add(new CodeMethodInvokeExpression(
                new CodeThisReferenceExpression(),
                    "InitializeComponent", new CodeExpression[] { }));

            ctd.Members.Add(constructor);
        }

        public void AddImport(string namespace_value)
        {
            cn.Imports.Add(new CodeNamespaceImport(namespace_value));
        }

        public void AddComponent_Label(string name)
        {
            ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.Label), "lbl_" + name));

            init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("lbl_" + name),
                new CodeObjectCreateExpression(typeof(System.Windows.Forms.Label), new CodeExpression[] { })));

            setup_component.Add(new CodeCommentStatement(""));
            setup_component.Add(new CodeCommentStatement("lbl_" + name));
            setup_component.Add(new CodeCommentStatement(""));
            component_list.Add(new string[]{"lbl_" + name,"-1"});

            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("lbl_" + name), "Name"), new CodePrimitiveExpression("lbl_" + name)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("lbl_" + name), "Text"), new CodePrimitiveExpression(name)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("lbl_" + name), "AutoSize"), new CodePrimitiveExpression(true)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("lbl_" + name), "TabIndex"), new CodePrimitiveExpression(tabindex)));
            tabindex++;
        }

        public void AddComponent_ComboBox(string name, int rownumber)
        {
            ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.ComboBox), "cb_" + name));

            init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("cb_" + name),
                new CodeObjectCreateExpression(typeof(System.Windows.Forms.ComboBox), new CodeExpression[] { })));

            setup_component.Add(new CodeCommentStatement(""));
            setup_component.Add(new CodeCommentStatement("cb_" + name));
            setup_component.Add(new CodeCommentStatement(""));
            component_list.Add(new string[] { "cb_" + name, "" + rownumber });

            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("cb_" + name), "Name"), new CodePrimitiveExpression("cb_" + name)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("cb_" + name), "DropDownStyle"), new CodeFieldReferenceExpression(
                    new CodeTypeReferenceExpression(typeof(System.Windows.Forms.ComboBoxStyle)), "DropDownList")));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("cb_" + name), "Size"), new CodeObjectCreateExpression(typeof(System.Drawing.Size),
                    new CodeExpression[] { new CodePrimitiveExpression(250), new CodePrimitiveExpression(23) })));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("cb_" + name), "TabIndex"), new CodePrimitiveExpression(tabindex)));
            tabindex++;
        }

        public void AddComponent_NumericUpDown(string name, int decimalplaces, int rownumber)
        {
            ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.NumericUpDown), "nud_" + name));

            init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("nud_" + name),
                new CodeObjectCreateExpression(typeof(System.Windows.Forms.NumericUpDown), new CodeExpression[] { })));

            setup_component.Add(new CodeCommentStatement(""));
            setup_component.Add(new CodeCommentStatement("nud_" + name));
            setup_component.Add(new CodeCommentStatement(""));
            component_list.Add(new string[]{"nud_" + name, "" + rownumber});

            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("nud_" + name), "Name"), new CodePrimitiveExpression("nud_" + name)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("nud_" + name),"Size"), new CodeObjectCreateExpression(typeof(System.Drawing.Size),
                    new CodeExpression[] { new CodePrimitiveExpression(250), new CodePrimitiveExpression(20) })));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("nud_" + name), "DecimalPlaces"), new CodePrimitiveExpression(decimalplaces)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("nud_" + name), "Maximum"), new CodeFieldReferenceExpression(new CodeTypeReferenceExpression(typeof(Decimal)), "MaxValue")));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("nud_" + name), "TabIndex"), new CodePrimitiveExpression(tabindex)));
            tabindex++;
        }

        public void AddComponent_CheckBox(string name, bool defaultvalue, int rownumber)
        {
            ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.CheckBox), "chkb_" + name));

            init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("chkb_" + name),
                new CodeObjectCreateExpression(typeof(System.Windows.Forms.CheckBox), new CodeExpression[] { })));

            setup_component.Add(new CodeCommentStatement(""));
            setup_component.Add(new CodeCommentStatement("chkb_" + name));
            setup_component.Add(new CodeCommentStatement(""));
            component_list.Add(new string[]{"chkb_" + name, "" + rownumber});

            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("chkb_" + name), "Name"), new CodePrimitiveExpression("chkb_" + name)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("chkb_" + name), "Checked"), new CodePrimitiveExpression(defaultvalue)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("chkb_" + name), "Size"), new CodeObjectCreateExpression(typeof(System.Drawing.Size),
                    new CodeExpression[] { new CodePrimitiveExpression(250), new CodePrimitiveExpression(20) })));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("chkb_" + name), "TabIndex"), new CodePrimitiveExpression(tabindex)));
            tabindex++;
        }

        public void AddComponent_DateTimePicker(string name, int rownumber)
        {
            ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.DateTimePicker), "dtp_" + name));

            init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("dtp_" + name),
                new CodeObjectCreateExpression(typeof(System.Windows.Forms.DateTimePicker), new CodeExpression[] { })));

            setup_component.Add(new CodeCommentStatement(""));
            setup_component.Add(new CodeCommentStatement("dtp_" + name));
            setup_component.Add(new CodeCommentStatement(""));
            component_list.Add(new string[]{"dtp_" + name, "" + rownumber});

            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("dtp_" + name), "Name"), new CodePrimitiveExpression("dtp_" + name)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("dtp_" + name), "Size"), new CodeObjectCreateExpression(typeof(System.Drawing.Size),
                    new CodeExpression[] { new CodePrimitiveExpression(250), new CodePrimitiveExpression(20) })));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("dtp_" + name), "TabIndex"), new CodePrimitiveExpression(tabindex)));
            tabindex++;
        }

        public void AddComponent_TextBox(string name, int length, int rownumber)
        {
            bool multiline = length > 49 ? true : false;
            ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.TextBox), "tb_" + name));

            init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("tb_" + name),
                new CodeObjectCreateExpression(typeof(System.Windows.Forms.TextBox), new CodeExpression[] { })));

            setup_component.Add(new CodeCommentStatement(""));
            setup_component.Add(new CodeCommentStatement("tb_" + name));
            setup_component.Add(new CodeCommentStatement(""));
            component_list.Add(new string[]{"tb_" + name, "" + rownumber});

            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("tb_" + name), "Name"), new CodePrimitiveExpression("tb_" + name)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("tb_" + name),"Multiline"), new CodePrimitiveExpression(true)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                            new CodeVariableReferenceExpression("tb_" + name), "MaxLength"), new CodePrimitiveExpression(length)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("tb_" + name), "Size"), new CodeObjectCreateExpression(typeof(System.Drawing.Size),
                    new CodeExpression[] { new CodePrimitiveExpression(250), new CodePrimitiveExpression(multiline ? 60 : 20) })));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("tb_" + name), "ScrollBars"),new CodeFieldReferenceExpression(
                    new CodeTypeReferenceExpression(typeof(System.Windows.Forms.ScrollBars)),multiline ? "Vertical": "None")));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("tb_" + name), "TabIndex"), new CodePrimitiveExpression(tabindex)));
            tabindex++;
        }

        public void AddDefaultValues(string name, string table, string display, string value)
        {
            CodeMemberMethod cmm_adddef = new CodeMemberMethod();
            cmm_adddef.Name = "AddDefaultValues_" + name;
            cmm_adddef.ReturnType = new CodeTypeReference(typeof(void));
            CodeConstructor cons = (CodeConstructor)ctd.Members[0];
            cons.Statements.Add(
                new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), "AddDefaultValues_" + name, new CodeExpression[] { }));
            ctd.Members[0] = cons;

            cmm_adddef.Statements.Add(new CodeVariableDeclarationStatement(typeof(object[]), "tmp",
                new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(
                    "FolderEngine"), "DecryptDisplayCode",
                    new CodeExpression[]{ new CodePrimitiveExpression(display), new CodePrimitiveExpression(table)})));
            cmm_adddef.Statements.Add(new CodeVariableDeclarationStatement(typeof(object[]), "returndata",
                new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(
                    "GlobalObjectsSQL"), "ExecuteSingleTableRead",
                    new CodeExpression[]{new CodeArrayCreateExpression(typeof(string),new CodeExpression[]{
                        new CodeMethodInvokeExpression(new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("tmp"), new CodeExpression[]{
                            new CodePrimitiveExpression(0)}),"ToString", new CodeExpression[]{}), new CodePrimitiveExpression(table + "." + value)}), 
                        new CodeBinaryOperatorExpression(new CodePrimitiveExpression(table + " "), CodeBinaryOperatorType.Add,new CodeMethodInvokeExpression(
                            new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("tmp"), new CodeExpression[]{
                            new CodePrimitiveExpression(1)}),"ToString", new CodeExpression[]{})),new CodePrimitiveExpression("")})));
            
            cmm_adddef.Statements.Add(new CodeMethodInvokeExpression(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("cb_" + name), "Items"),
                "Clear", new CodeExpression[] { }));
            cmm_adddef.Statements.Add(new CodeVariableDeclarationStatement(typeof(EdgeStatz.ESSystems.Objects.DisplayValueObject[]),"array",
                new CodeArrayCreateExpression(typeof(EdgeStatz.ESSystems.Objects.DisplayValueObject[]), new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("returndata"),"Length"))));
            List<CodeStatement> loopstatements = new List<CodeStatement> { };
            loopstatements.Add(new CodeVariableDeclarationStatement(typeof(object[]), "data",
                new CodeCastExpression(typeof(object[]), new CodeArrayIndexerExpression(
                    new CodeVariableReferenceExpression("returndata"), new CodeExpression[] { new CodeVariableReferenceExpression("i") }))));
            
            loopstatements.Add(new CodeAssignStatement(
                new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("array"),new CodeExpression[]{ new CodeVariableReferenceExpression("i")}) 
                , new CodeObjectCreateExpression(typeof(EdgeStatz.ESSystems.Objects.DisplayValueObject),
                    new CodeExpression[] {new CodeMethodInvokeExpression(new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("data"), 
                        new CodeExpression[]{new CodePrimitiveExpression(0)}),"ToString", new CodeExpression[]{}), new CodeMethodInvokeExpression(
                            new CodeCastExpression(typeof(System.Guid),new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("data"),
                                new CodeExpression[]{new CodePrimitiveExpression(1)})),"ToString",new CodeExpression[]{})})
                ));
                            
            cmm_adddef.Statements.Add(new CodeIterationStatement(
                new CodeVariableDeclarationStatement(typeof(int), "i", new CodePrimitiveExpression(0)),
                new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.LessThan,
                    new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("returndata"), "Length")),
                new CodeAssignStatement(new CodeVariableReferenceExpression("i"), new CodeBinaryOperatorExpression(
                    new CodeVariableReferenceExpression("i"), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(1))),
                loopstatements.ToArray()));

            cmm_adddef.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("cb_" + name), "DataSource"), new CodeVariableReferenceExpression("array")));
                        
            cmm_adddef.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("cb_" + name), "DisplayMember"), new CodePrimitiveExpression("Display")));
            
            cmm_adddef.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("cb_" + name), "ValueMember"), new CodePrimitiveExpression("Value")));

            ctd.Members.Add(cmm_adddef);
        }
        
        public void AddTab(string tabfoldername, string tabtablename, string tabidcol, int idcol) 
        {
            if (!istabbed) 
            { 
                istabbed = true;
                tabpage_list.Clear();
                tabpage_list.Add(new string[] { "tp_" + classname});
                ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.TabPage), "tp_" + classname));

                init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("tp_" + classname),
                    new CodeObjectCreateExpression(typeof(System.Windows.Forms.TabPage), new CodeExpression[] { })));

                setup_component.Add(new CodeCommentStatement(""));
                setup_component.Add(new CodeCommentStatement("tp_" + classname));
                setup_component.Add(new CodeCommentStatement(""));

                setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("tp_" + classname), "Name"), new CodePrimitiveExpression("tp_" + classname)));
                setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("tp_" + classname), "Text"), new CodePrimitiveExpression(folderdef.Name)));
                setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("tp_" + classname), "Padding"), new CodeObjectCreateExpression(
                        typeof(System.Windows.Forms.Padding),new CodeExpression[]{new CodePrimitiveExpression(3)})));
                setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("tp_" + classname), "UseVisualStyleBackColor"), new CodePrimitiveExpression(true)));
            }
            string tabname = tabfoldername.Replace(' ','_');
            tabpage_list.Add(new string[] { "tp_" + tabname, tabfoldername, tabtablename,tabidcol, idcol.ToString() });
            ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.TabPage), "tp_" + tabname));

            init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("tp_" + tabname),
                new CodeObjectCreateExpression(typeof(System.Windows.Forms.TabPage), new CodeExpression[] { })));

            setup_component.Add(new CodeCommentStatement(""));
            setup_component.Add(new CodeCommentStatement("tp_" + tabname));
            setup_component.Add(new CodeCommentStatement(""));

            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("tp_" + tabname), "Name"), new CodePrimitiveExpression("tp_" + tabname)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("tp_" + tabname), "Text"), new CodePrimitiveExpression(tabfoldername)));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("tp_" + tabname), "Padding"), new CodeObjectCreateExpression(
                    typeof(System.Windows.Forms.Padding), new CodeExpression[] { new CodePrimitiveExpression(3) })));
            setup_component.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("tp_" + tabname), "UseVisualStyleBackColor"), new CodePrimitiveExpression(true)));
            
        }

        //public void AddIDColumn(string name, string type)
        //{
        //    ctd.Members.Add(new CodeMemberField(typeof(System.Guid),"keyVal"));
        //    idcol_name = name;
        //}

        public FormDefinition WriteSourceCode()
        {
            AddConstructor_LoadValues();
            AddMethod_InitializeComponent();
            AddSaveMethod();
            
            cn.Types.Add(ctd);
            cu.Namespaces.Add(cn);

            Microsoft.CSharp.CSharpCodeProvider provider = new Microsoft.CSharp.CSharpCodeProvider();
            System.CodeDom.Compiler.CodeGeneratorOptions options = new System.CodeDom.Compiler.CodeGeneratorOptions();

            provider.GenerateCodeFromCompileUnit(cu, writer, options);

            writer.Close();

            return new FormDefinition(classname, folderdef.Name, GlobalSystemSettings.SystemFolderPath +
                (GlobalSystemSettings.SystemFolderPath.EndsWith("\\") ? "" : "\\") + classname + "_Form.cs",
                new string[] { "System.dll", "System.Drawing.dll", "System.Windows.Forms.dll", "EdgeStatz.ESSystems.dll", "EdgeStatz.ModelEngine.dll" }, new string[]{});            
        }
        
        private void AddMethod_InitializeComponent()
        {
            CodeMemberMethod cmm_init = new CodeMemberMethod();
            cmm_init.Name = "InitializeComponent";
            cmm_init.ReturnType = new CodeTypeReference(typeof(void));

            ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.TableLayoutPanel), "_tableLayoutPanel"));
            init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("_tableLayoutPanel"),
                new CodeObjectCreateExpression(typeof(System.Windows.Forms.TableLayoutPanel), new CodeExpression[] { })));
            if(istabbed)
                init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("_tabControl"),
                    new CodeObjectCreateExpression(typeof(System.Windows.Forms.TabControl), new CodeExpression[] { })));

            cmm_init.Statements.AddRange(init_component.ToArray());

            cmm_init.Statements.Add(new CodeCommentStatement(""));
            cmm_init.Statements.Add(new CodeCommentStatement("_tableLayoutPanel"));
            cmm_init.Statements.Add(new CodeCommentStatement(""));
                        
            cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("_tableLayoutPanel"), 
                "SuspendLayout", new CodeExpression[] { }));
            cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), 
                "SuspendLayout", new CodeExpression[] { }));
            cmm_init.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("_tableLayoutPanel"), "AutoScroll"), new CodePrimitiveExpression(true)));
            cmm_init.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("_tableLayoutPanel"), "ColumnCount"), new CodePrimitiveExpression(2)));
            cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("_tableLayoutPanel"), "ColumnStyles"), "Add", new CodeExpression[] { 
                    new CodeObjectCreateExpression(typeof(System.Windows.Forms.ColumnStyle), new CodeExpression[] { }) }));
            cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("_tableLayoutPanel"), "ColumnStyles"), "Add", new CodeExpression[] { 
                    new CodeObjectCreateExpression(typeof(System.Windows.Forms.ColumnStyle), new CodeExpression[] { }) }));

            for (int i = 0; i < component_list.Count; i++)
            {
                cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("_tableLayoutPanel"), "Controls"), "Add", new CodeExpression[] { 
                        new CodeVariableReferenceExpression(component_list[i].GetValue(0).ToString()), new CodePrimitiveExpression(i % 2), new CodePrimitiveExpression(i / 2) }));
            }

            cmm_init.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(
                "_tableLayoutPanel"), "RowCount"), new CodePrimitiveExpression((component_list.Count / 2) + 1)));

            for (int j = 0; j < (component_list.Count / 2) + 1; j++)
            {
                cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(
                    "_tableLayoutPanel"), "RowStyles"), "Add", new CodeExpression[] { new CodeObjectCreateExpression(
                        typeof(System.Windows.Forms.RowStyle), new CodeExpression[] { }) }));
            }

            cmm_init.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("_tableLayoutPanel"), "Dock"),new CodeFieldReferenceExpression(
                    new CodeTypeReferenceExpression(typeof(System.Windows.Forms.DockStyle)), "Fill")));
            cmm_init.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("_tableLayoutPanel"), "Name"), new CodePrimitiveExpression("_tableLayoutPanel")));
            cmm_init.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("_tableLayoutPanel"), "AutoSize"),new CodePrimitiveExpression(true)));
            cmm_init.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                new CodeVariableReferenceExpression("_tableLayoutPanel"), "TabIndex"), new CodePrimitiveExpression(0)));

            cmm_init.Statements.AddRange(setup_component.ToArray());

            if (istabbed)
            {
                cmm_init.Statements.Add(new CodeCommentStatement(""));
                cmm_init.Statements.Add(new CodeCommentStatement("_tabControl"));
                cmm_init.Statements.Add(new CodeCommentStatement(""));

                ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.TabControl), "_tabControl"));
                init_component.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("_tabControl"),
                    new CodeObjectCreateExpression(typeof(System.Windows.Forms.TabControl), new CodeExpression[] { })));

                foreach(string[] tabname in tabpage_list.ToArray())
                    cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(
                        new CodeVariableReferenceExpression("_tabControl"),"Controls"),"Add",
                        new CodeExpression[]{new CodeVariableReferenceExpression(tabname[0])}));
                
                cmm_init.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("_tabControl"), "Dock"), new CodeFieldReferenceExpression(
                        new CodeTypeReferenceExpression(typeof(System.Windows.Forms.DockStyle)), "Fill")));
                cmm_init.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("_tabControl"), "Name"), new CodePrimitiveExpression("_tabControl")));
                cmm_init.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                    new CodeVariableReferenceExpression("_tabControl"), "SelectedIndex"), new CodePrimitiveExpression(0)));
            }

            cmm_init.Statements.Add(new CodeCommentStatement(""));
            cmm_init.Statements.Add(new CodeCommentStatement(classname));
            cmm_init.Statements.Add(new CodeCommentStatement(""));

            if (istabbed)
            {
                cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(
                    new CodeThisReferenceExpression(), "Controls"), "Add", new CodeExpression[] { new CodeVariableReferenceExpression("_tabControl") }));
                cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(
                        new CodeVariableReferenceExpression(tabpage_list[0].GetValue(0).ToString()), "Controls"), "Add", new CodeExpression[] { new CodeVariableReferenceExpression("_tableLayoutPanel") }));
            }
            else
            {
                cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(
                    new CodeThisReferenceExpression(), "Controls"), "Add", new CodeExpression[] { new CodeVariableReferenceExpression("_tableLayoutPanel") }));
            }

            cmm_init.Statements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(
                new CodeThisReferenceExpression(), "Name"), new CodePrimitiveExpression(classname)));
            setup_component.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(
                new CodeThisReferenceExpression(), "Size"), new CodeObjectCreateExpression(typeof(System.Drawing.Size),
                    new CodeExpression[] { new CodePrimitiveExpression(750), new CodePrimitiveExpression(600) })));
            

            cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("_tableLayoutPanel"), 
                "ResumeLayout", new CodeExpression[] { new CodePrimitiveExpression(false) }));
            cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("_tableLayoutPanel"), 
                "PerformLayout", new CodeExpression[] { }));
            cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(), 
                "ResumeLayout", new CodeExpression[] { new CodePrimitiveExpression(false) }));
            cmm_init.Statements.Add(new CodeMethodInvokeExpression(new CodeThisReferenceExpression(),
                "PerformLayout", new CodeExpression[] { }));

            ctd.Members.Add(cmm_init);
        }

        private void AddConstructor_LoadValues()
        {
            CodeConstructor constructor2 = new CodeConstructor();
            constructor2.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "key"));
            constructor2.Attributes = MemberAttributes.Public;
            constructor2.ChainedConstructorArgs.Add(new CodeSnippetExpression());
            
            ctd.Members.Add(new CodeMemberField(typeof(System.Guid), "keyVal"));

            constructor2.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("keyVal"), 
                new CodeObjectCreateExpression(typeof(System.Guid), new CodeExpression[]{new CodeVariableReferenceExpression("key")})));

            constructor2.Statements.Add(new CodeVariableDeclarationStatement(typeof(object[]), "data",
                new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("GlobalObjectsSQL"), "ExecuteSingleTableRead", 
                    new CodeExpression[]{ new CodePrimitiveExpression(null), new CodePrimitiveExpression(tabledef.Name),
                    new CodeBinaryOperatorExpression(new CodePrimitiveExpression(folderdef.ValueExp + " = '"), CodeBinaryOperatorType.Add, 
                        new CodeBinaryOperatorExpression(new CodeVariableReferenceExpression("key"), CodeBinaryOperatorType.Add,
                            new CodePrimitiveExpression("'")))})));

            constructor2.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(
                new CodePropertyReferenceExpression(new CodeVariableReferenceExpression("data"), "Length"), CodeBinaryOperatorType.GreaterThan, new CodePrimitiveExpression(0)),
                new CodeStatement[]{new CodeAssignStatement(new CodeVariableReferenceExpression("data"), new CodeCastExpression(typeof(object[]), new CodeArrayIndexerExpression(
                    new CodeVariableReferenceExpression("data"), new CodeExpression[]{new CodePrimitiveExpression(0)})))}));

            foreach (string[] name in component_list.ToArray())
            {
                switch ((string)name[0].Split('_').GetValue(0))
                {
                    case "cb":
                        constructor2.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                            new CodeVariableReferenceExpression(name[0]), "SelectedValue"), new CodeMethodInvokeExpression(new CodeArrayIndexerExpression(
                                new CodeVariableReferenceExpression("data"), new CodeExpression[] { new CodePrimitiveExpression(Convert.ToInt32(name[1])) }),
                                "ToString", new CodeExpression[]{})));
                        break;
                    case "nud":
                        constructor2.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                            new CodeVariableReferenceExpression(name[0]), "Value"), 
                            new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(Convert)),
                                "ToDecimal", new CodeExpression[]{new CodeArrayIndexerExpression(new CodeVariableReferenceExpression("data"), 
                                    new CodeExpression[] { new CodePrimitiveExpression(Convert.ToInt32(name[1]))})})));
                        break;
                    case "chkb":
                        constructor2.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                            new CodeVariableReferenceExpression(name[0]), "Checked"), new CodeCastExpression(typeof(bool), new CodeArrayIndexerExpression(
                                new CodeVariableReferenceExpression("data"), new CodeExpression[] { new CodePrimitiveExpression(Convert.ToInt32(name[1])) }))));
                        break;
                    case "dtp":
                        constructor2.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                            new CodeVariableReferenceExpression(name[0]), "Value"), new CodeCastExpression(typeof(System.DateTime), new CodeArrayIndexerExpression(
                                new CodeVariableReferenceExpression("data"), new CodeExpression[] { new CodePrimitiveExpression(Convert.ToInt32(name[1])) }))));
                        break;
                    case "tb":
                        constructor2.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                            new CodeVariableReferenceExpression(name[0]), "Text"), new CodeCastExpression(typeof(string), new CodeArrayIndexerExpression(
                                new CodeVariableReferenceExpression("data"), new CodeExpression[] { new CodePrimitiveExpression(Convert.ToInt32(name[1])) }))));
                        break;
                }
            }
            if (istabbed)
            {
                for (int j = 1; j < tabpage_list.Count;j++ )
                {
                    string[] tabname = tabpage_list[j];
                    ctd.Members.Add(new CodeMemberField(typeof(System.Windows.Forms.UserControl), "uc_" + tabname[1].Replace(' ', '_')));
                    constructor2.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("uc_" + tabname[1].Replace(' ', '_')),
                        new CodeObjectCreateExpression("EdgeStatz.GeneratedForms." + tabname[1].Replace(' ', '_'), new CodeExpression[] {
                        new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(typeof(GlobalObjectsSQL)),"ExecuteSingleTableRead",new CodeExpression[]{
                        new CodePrimitiveExpression(null), new CodePrimitiveExpression(tabname[2]), new CodeBinaryOperatorExpression(
                        new CodePrimitiveExpression(tabname[3] + " = '"),CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression(new CodeMethodInvokeExpression(new CodeArrayIndexerExpression(
                        new CodeVariableReferenceExpression("data"),new CodeExpression[]{
                        new CodePrimitiveExpression(Convert.ToInt32(tabname[4]))}),"ToString", new CodeExpression[]{}),CodeBinaryOperatorType.Add,new CodePrimitiveExpression("'")))})})));

                    constructor2.Statements.Add(new CodeAssignStatement(new CodePropertyReferenceExpression(
                        new CodeVariableReferenceExpression("uc_" + tabname[1].Replace(' ', '_')),"Dock"),
                        new CodePropertyReferenceExpression(new CodeTypeReferenceExpression(typeof(System.Windows.Forms.DockStyle)), "Fill")));

                    constructor2.Statements.Add(new CodeMethodInvokeExpression(new CodePropertyReferenceExpression(
                        new CodeVariableReferenceExpression(tabname[0]),"Controls"
                        ),"Add", new CodeExpression[]{new CodeVariableReferenceExpression("uc_" + tabname[1].Replace(' ', '_'))}));
                }
            }
            ctd.Members.Add(constructor2);
        }

        private void AddSaveMethod()
        {
            CodeMemberMethod cmm_save = new CodeMemberMethod();
            cmm_save.Name = "Save";
            cmm_save.ReturnType = new CodeTypeReference(typeof(void));
            cmm_save.Attributes = MemberAttributes.Public;

            List<CodeExpression> colnames = new List<CodeExpression> { };
            List<CodeExpression> values = new List<CodeExpression> { };

            foreach (string[] name in component_list.ToArray())
            {
                string[] comp = name[0].Split('_');
                switch (comp[0])
                {
                    case "lbl":
                        continue;
                    case "cb":
                        values.Add(new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(name[0]), "SelectedValue"));
                        break;
                    case "nud":
                        values.Add(new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(name[0]), "Value"));
                        break;
                    case "chkb":
                        values.Add(new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(name[0]), "Checked"));
                        break;
                    case "dtp":
                        values.Add(new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(name[0]), "Value"));
                        break;
                    case "tb":
                        values.Add(new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(name[0]), "Text"));
                        break;
                    default:
                        values.Add(new CodePropertyReferenceExpression(new CodeVariableReferenceExpression(name[0]), "Value"));
                        break;
                }
                colnames.Add(new CodePrimitiveExpression(comp[1]));
            }

            List<CodeStatement> truestate = new List<CodeStatement> { };
            CodeStatement falsestate;

            truestate.Add(new CodeVariableDeclarationStatement(typeof(object), "key",
                new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("GlobalObjectsSQL"), "ExecuteSingleRowInsert",new CodeExpression[]{
                new CodePrimitiveExpression(folderdef.TableName), new CodeArrayCreateExpression(typeof(string),colnames.ToArray()),
                new CodeArrayCreateExpression(typeof(object),values.ToArray()), new CodePrimitiveExpression(folderdef.ValueExp)})));
            truestate.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("keyVal"), new CodeObjectCreateExpression(
                typeof(System.Guid), new CodeExpression[]{new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("key"), "ToString", new CodeExpression[]{})})));

            falsestate = new CodeExpressionStatement(new CodeMethodInvokeExpression(new CodeTypeReferenceExpression("GlobalObjectsSQL"), "ExecuteSingleRowUpdate", new CodeExpression[]{
                new CodePrimitiveExpression(folderdef.TableName), new CodeArrayCreateExpression(typeof(string),colnames.ToArray()),
                new CodeArrayCreateExpression(typeof(object),values.ToArray()), new CodePrimitiveExpression(folderdef.ValueExp),new CodeMethodInvokeExpression(
                    new CodeVariableReferenceExpression("keyVal"),"ToString", new CodeExpression[]{})}));

            cmm_save.Statements.Add(new CodeConditionStatement(new CodeMethodInvokeExpression(
                new CodeVariableReferenceExpression("keyVal"), "Equals", new CodeExpression[] { new CodePropertyReferenceExpression(
                    new CodeTypeReferenceExpression(typeof(System.Guid)),"Empty") }), truestate.ToArray(), new CodeStatement[]{falsestate}));
            ctd.Members.Add(cmm_save);
        }
    }
}
